﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace Domain
{
    public class Game
    {
        protected const int Max_Player = 14;
        protected const int Max_Playing_Player = 8;
        protected const int Max_Substitution_Player = 6;

        [Key]
        public int GameId { get; set; }
        public DateTime GameDateAndTime { get; set; }
        public virtual ICollection<GamePlayer> GamePlayers { get; set; }
        public virtual GameStatus GameStatus { get; set; }

        public Game()
        { 
            GamePlayers = new List<GamePlayer>();
        }

        public Game(DateTime gameDateTime) : this()
        {
            if (!IsValidGameTime())
            {
                throw new System.ApplicationException("Invalid Game Date and time. please correct before creating");
            }

            GameDateAndTime = gameDateTime;
            GameStatus = GameStatus.Created;
        }

        public void Publish()
        {
            if (GameStatus != GameStatus.Created)
            {
                throw new System.ApplicationException("Invalid Status : Game can not be published for this status");
            }
            if (IsValidGameTime())
            {
                throw new System.ApplicationException("Invalid Game Date and time. please correct before publishing");
            }
            GameStatus = Domain.GameStatus.Published;

        }

        public void AddPlayer(Player player)
        {
            if (GamePlayers.Any(a => a.Player.PlayerId == player.PlayerId))
            {
                return; // Player in list already do nothing // better to display error message
            }

            if (GameStatus != Domain.GameStatus.Published)
            {
                throw new System.ApplicationException("Invalid Status : Players can not be added in current status");    
            }
            if (GamePlayers.Count >= Max_Player)
            {
                throw new System.ApplicationException("Max player Limit reached sorry");
            }

            if (!IsMaxPlayingReached())
            {
                GamePlayers.Add(new GamePlayer(player, GamePlayerStatus.Playing));
            }
            else
            {
                GamePlayers.Add(new GamePlayer(player, GamePlayerStatus.Substituting));
            }
        }

        protected bool IsValidGameTime()
        {
            return GameDateAndTime < DateTime.Now;            
        }

        protected bool IsMaxPlayingReached()
        {
            return GamePlayers.Count(a => a.PlayingStatus == GamePlayerStatus.Playing) >= Max_Playing_Player;
        }

        protected bool IsMaxSubstitutingReached()
        {
            return GamePlayers.Count(a => a.PlayingStatus == GamePlayerStatus.Substituting) >= Max_Substitution_Player;
        }
        
        public ICollection<Player> GetPlayingPlayers()
        {
            return GamePlayers.Where(a => a.PlayingStatus == GamePlayerStatus.Playing).Select(x => x.Player).ToList();
        }

        public ICollection<Player> GetSubstitutingPlayers()
        {
            return GamePlayers.Where(a => a.PlayingStatus == GamePlayerStatus.Substituting).Select(x => x.Player).ToList();
        }
    }
}
